using Gameplay.PVE.Entity;
using Gameplay.PVE.Utils;
using UnityEngine;

namespace Gameplay.PVE
{
    //移动射击路径
    public class MoveAttackRoadPath : UnitRoadPath
    {
        
        
        public override void Init(UnitBase unit)
        {
            unit.Data.hasReachAttackPosition = false;
            base.Init(unit);
            actionName = "Run";
            actionSpeed = 1f;
            enemyMeleeFindPathState = 0;
        }

         public override void OnTransmit(ETransmitType type,BaseTransmitArg arg)
        {
            base.OnTransmit(type,arg);
            if (type == ETransmitType.RePath)
            {
                needRepath = true;
            }
        }
        
        public override void Update()
        {
            base.Update();
            if (unit.Data.isManualMoving || unit.Data.moveState == 1)
            {
                UpdateManualMoving();
            }
            else
            {
                if (unit.Data.team == 0)
                {
                    if (!PveManager.Instance.rpgStart)
                    {
                        MoveToTargetPosition(unit.Data.birthPosition);
                        if (Vector3.Distance(unit.Data.birthPosition,position) < unit.Data.configMoveSpeed * TimeManager.LogicDeltaTime)
                        {
                            unit.Data.moveState = 0;
                        }
                        else
                        {
                            unit.Data.moveState = 2;
                        }
                    }
                    else if (unit.Data.rangeType == 1 || unit.Data.isSummonUnit)
                    {
                        UpdateNormalRpgSelfMelee();
                    }
                    else if (PveGlobalVlues.selfMoveType == 1 || (PveGlobalVlues.selfMoveType == 2 && unit.Data.rangeType == 1) || PveGlobalVlues.selfMoveType == 0 && unit.Data.attackPosition != Vector3.zero)
                    {
                        //UpdateNormalRpgSelf();
                        UpdateNormalRpgSelfWithHidePoint();
                    }
                    else
                    {
                        position = unit.Data.position;
                    }
                }
                else
                {
                    if (unit.Data.rangeType == 1)
                    {
                        UpdateEnemyMelee();
                        BattleLog.UnitLog(unit,"state" + enemyMeleeFindPathState);
                    }
                    else
                    {
                        UpdateNormalRpg();
                    }
                    
                }
                if (position == unit.Data.position)
                {
                    unit.Data.targetMoveSpeed = 0;
                    unit.Data.moveState = 0;
                    isFinish = true;
                }
                else
                {
                    if (!unit.Data.isGoingToHidePoint)
                    {
                        unit.Data.RemoveAstar();
                    }
                }
            }
        }

        private Vector3 lastManualForward;
        private Vector3 lastManualAvailablePosition;
        private float availablePositionTime;
        private Vector3 lastTargetPosition;
        private Vector3 lastRepathTarget;

        private float xMin;
        private float xMax;
        private float zMin;
        private float zMax;

        public void SetRestriction(float xMin,float xMax,float zMin,float zMax)
        {
            this.xMin = xMin;
            this.xMax = xMax;
            this.zMin = zMin;
            this.zMax = zMax;
        }

        private void UpdateNormalRpgSelfMelee()
        {
            var targetPosition = unit.Data.targetPosition;
            if (unit.Data.lockTarget == null || unit.Data.lockTarget.Data.isDead)
            {
                if (unit.Data.position.x > PveGlobalVlues.SelfMeleeLine2)
                {
                    targetPosition = unit.Data.birthPosition;
                    if (!IsInRepathFailCD() && !IsInRepathSuccessCD() || !isFindPathSuccess)
                    {
                        UpdateAStarPath(unit.Data.position, targetPosition,true);
                        lastRepathTime = TimeManager.logicTime;
                        RefreshRepathCD();
                    }
                    UpdateRoadPath();
                }
                else
                {
                    targetPosition = unit.Data.targetPosition;
                    unit.Data.SetTargetForward(Vector3.right);
                    position = unit.Data.position;
                }
                lastLockTarget = null;
            }
            else if (unit.Data.IsAttackInRange())
            {
                if (lastLockTarget == null)
                {
                    lastRepathTime = 0;
                }
                lastLockTarget = unit.Data.lockTarget;
                unit.Data.isSelfMeleeAtRegion = false;
                if (PveFindPathManager.Instance.CheckIsWalkable(unit.Data.position, unit.Data.id))
                {
                    position = unit.Data.position;
                }
                else if (IsInRepathFailCD())
                {
                    UpdateRoadPath();
                }
                else
                {
                    UpdateAStarPath(unit.Data.position, targetPosition,true);
                    lastRepathTime = TimeManager.logicTime;
                    UpdateRoadPath();
                    lastRepathTarget = targetPosition;
                }
                
            }
            else
            {
                if (lastLockTarget == null)
                {
                    lastRepathTime = 0;
                }
                lastLockTarget = unit.Data.lockTarget;
                unit.Data.isSelfMeleeAtRegion = false;
                /*if (!unit.Data.hasReachAttackPosition && unit.Data.)
                {
                    targetPosition = unit.Data.attackPosition;
                    if (Vector3.Distance(unit.Data.position, targetPosition) <= 0.1f)
                    {
                        unit.Data.hasReachAttackPosition = true;
                    }
                }
                else*/
                {
                    targetPosition = unit.Data.lockTarget.Data.position;
                }
                
                //if (targetPosition != lastRepathTarget && TimeManager.logicTime - lastRepathTime > 0.5f)
                if (!IsInRepathFailCD() && !IsInRepathSuccessCD() || !isFindPathSuccess)
                {
                    UpdateAStarPath(unit.Data.position, targetPosition,true);
                    lastRepathTime = TimeManager.logicTime;
                    RefreshRepathCD();
                }
                UpdateRoadPath();
                if (position.x > PveGlobalVlues.SelfMeleeLine + 1)
                {
                    //position.x = PveGlobalVlues.SelfMeleeLine;
                    unit.Data.isSelfMeleeAtRegion = true;
                }
                lastRepathTarget = targetPosition;
            }
        }

        //敌方近战寻敌逻辑
        //还没进入射程时，每隔随机时间进行一次寻路
        //进入射程后，如果 当前位置不可达，则进行一次寻路，无论寻路是否成功，都作为最终路径

        private int enemyMeleeFindPathState = 0;//0还没进入射程   1 进入射程寻路成功  2 进入射程寻路失败 3 可以攻击
        private UnitBase lastLockTarget;
        private void UpdateEnemyMelee()
        {
            var targetPosition = unit.Data.targetPosition;

            if (lastLockTarget != unit.Data.lockTarget)
            {
                enemyMeleeFindPathState = 0;
            }

            unit.Data.isCanAttackByFindPath = false;
            if (unit.Data.lockTarget == null || unit.Data.lockTarget.Data.isDead)
            {
                targetPosition = unit.Data.targetPosition;
                unit.Data.SetTargetForward(unit.Data.forward);
                position = unit.Data.position;
                enemyMeleeFindPathState = 0;
            }
            else if (unit.Data.IsAttackInRange(1))
            {
                if (enemyMeleeFindPathState == 0)
                {
                    UpdateAStarPath(unit.Data.position, targetPosition,true);
                    if(isFindPathSuccess)
                    {
                        enemyMeleeFindPathState = 1;
                    }
                    else
                    {
                        enemyMeleeFindPathState = 2;
                    }
                }
                else if (enemyMeleeFindPathState == 1)
                {
                    if (unit.Data.IsAttackInRange())
                    {
                        if (!PveFindPathManager.Instance.CheckIsWalkable(unit.Data.position, unit.Data.id))
                        {
                            UpdateAStarPath(unit.Data.position, targetPosition,true);
                            if(isFindPathSuccess)
                            {
                                enemyMeleeFindPathState = 1;
                            }
                            else
                            {
                                enemyMeleeFindPathState = 2;
                            }
                        }
                        else
                        {
                            unit.Data.AddAstar();
                            enemyMeleeFindPathState = 3;
                            return;
                        }
                    }
                    else
                    {
                        if (lastRepathTarget != targetPosition && !IsInRepathSuccessCD() && !IsInRepathSuccessCD() || !isFindPathSuccess)
                        {
                            UpdateAStarPath(unit.Data.position, targetPosition,true);
                            lastRepathTime = TimeManager.logicTime;
                            lastRepathTarget = targetPosition;
                        }
                        
                        
                    }
                }
                else if (enemyMeleeFindPathState == 2)
                {
                    if (unit.Data.IsAttackInRange())
                    {
                        unit.Data.AddAstar();
                        enemyMeleeFindPathState = 3;
                        position = unit.Data.position;
                        return;
                    }
                }
                else if (enemyMeleeFindPathState == 3)
                {
                    if (unit.Data.IsInScreen() && unit.Data.IsAttackInRange())
                    {
                        position = unit.Data.position;
                        unit.Data.isCanAttackByFindPath = true;
                        return;
                    }
                }
                UpdateRoadPath();
            }
            else
            {
                enemyMeleeFindPathState = 0;
                if (!IsInRepathFailCD() && !IsInRepathSuccessCD() || !isFindPathSuccess)
                {
                    UpdateAStarPath(unit.Data.position, targetPosition,true);
                    if (!isFindPathSuccess)
                    {
                        pathList.Clear();
                        pathList.Add(unit.Data.position);
                        pathList.Add(targetPosition);
                    }
                    lastRepathTime = TimeManager.logicTime;
                    RefreshRepathCD();
                }
                UpdateRoadPath();
                lastRepathTarget = targetPosition;
            }

            lastLockTarget = unit.Data.lockTarget;
        }

        private bool IsInRepathFailCD()
        {
            if (isFindPathSuccess || lastFindPathFailTime == 0)
            {
                return false;
            }
            return TimeManager.logicTime - lastFindPathFailTime < 2;
        }

        private float repathCd = 0.5f;
        
        private bool IsInRepathSuccessCD()
        {
            if (!isFindPathSuccess)
            {
                return false;
            }
            return TimeManager.logicTime - lastRepathTime < repathCd;
        }

        private void UpdateNormalRpgSelfWithHidePoint()
        {
            var targetPosition = unit.Data.targetPosition;
            bool isForceEnd = false;
            if (unit.Data.lockTarget == null || unit.Data.lockTarget.Data.isDead)
            {
                targetPosition = unit.Data.targetPosition;
                unit.Data.SetTargetForward(unit.Data.forward);
            }
            else
            {
                if (unit.Data.attackPosition != Vector3.zero)
                {
                    targetPosition = unit.Data.attackPosition;
                    //if (PveGlobalVlues.HitAndRun == 1)
                    {
                        var d = Vector3.Distance(targetPosition, unit.Data.position);
                        if (d <= unit.Data.configMoveSpeed * TimeManager.LogicDeltaTime)
                        {
                            position = targetPosition;
                            unit.Data.attackPosition = targetPosition;
                            return;
                        }
                    }
                    
                    if (unit.Data.isGoingToHidePoint)
                    {
                        isForceEnd = true;
                    }
                }
                else
                {
                    unit.Data.isGoingToHidePoint = false;
                    var nearestPosition = unit.Data.lockTarget.Data.position + (unit.Data.position - unit.Data.lockTarget.Data.position).normalized * unit.Data.attackRange;
                    if (unit.Data.IsAttackInRange())
                    {
                        targetPosition = unit.Data.position;
                    }
                    else
                    {
                        if (!IsInArea(nearestPosition) && unit.Data.rangeType == 0)
                        {
                            unit.Data.SetLockTarget(null);
                            return;
                        }
                        else
                        {
                            targetPosition = unit.Data.lockTarget.Data.position;
                        }
                    }
                }
                if (targetPosition != lastRepathTarget)
                {
                    UpdateAStarPath(unit.Data.position, targetPosition,isForceEnd);
                    if (unit.Data.attackPosition != Vector3.zero && pathList.Count > 0)
                    {
                        unit.Data.attackPosition = pathList[pathList.Count - 1];
                    }
                }
                UpdateRoadPath();
                //ShowPath();
                lastRepathTarget = targetPosition;
            }
        }
        
        private void UpdateNormalRpgSelf()
        {
            var targetPosition = unit.Data.targetPosition;
            bool isForceEnd = false;
            if (unit.Data.lockTarget == null || unit.Data.lockTarget.Data.isDead)
            {
                targetPosition = unit.Data.targetPosition;
                unit.Data.SetTargetForward(unit.Data.forward);
            }
            else
            {
                if (unit.Data.attackPosition != Vector3.zero)
                {
                    targetPosition = unit.Data.attackPosition;
                    unit.Data.isGoingToHidePoint = true;
                    Debug.Log(unit.Data.id + " MoveToHidePoint " + targetPosition);
                    isForceEnd = true;
                }
                else
                {
                    unit.Data.isGoingToHidePoint = false;
                    var nearestPosition = unit.Data.lockTarget.Data.position + (unit.Data.position - unit.Data.lockTarget.Data.position).normalized * unit.Data.attackRange;
                    if (unit.Data.IsAttackInRange())
                    {
                        targetPosition = unit.Data.position;
                    }
                    else
                    {
                        if (!IsInArea(nearestPosition) && unit.Data.rangeType == 0)
                        {
                            unit.Data.SetLockTarget(null);
                            return;
                        }
                        else
                        {
                            targetPosition = unit.Data.lockTarget.Data.position;
                        }
                    }
                }
            }

            if (targetPosition != lastRepathTarget)
            {
                UpdateAStarPath(unit.Data.position, targetPosition,isForceEnd);
            }
            UpdateRoadPath();
            //ShowPath();
            lastRepathTarget = targetPosition;
        }

        private bool IsInArea(Vector3 position)
        {
            return position.x <= xMax && position.x >= xMin && position.z <= zMax && position.z >= zMin;
        }
        
        private void UpdateNormalRpg()
        {
            var targetPosition = unit.Data.targetPosition;
            unit.Data.isCanAttackByFindPath = true;
            if (true)
            {
                bool isForceEnd = false;
                if (unit.Data.lockTarget == null || unit.Data.lockTarget.Data.isDead)
                {
                    targetPosition = unit.Data.targetPosition;
                    unit.Data.SetTargetForward(unit.Data.forward);
                    position = unit.Data.position;
                    return;
                }
                else
                {
                    bool isAtAttackPosition = Vector3.Distance(unit.Data.attackPosition, unit.Data.position) <= 0.1f;
                    isAtAttackPosition = !PveGlobalVlues.enemyUseAttackPoint && isAtAttackPosition;
                    if (unit.Data.attackPosition == Vector3.zero)
                    {
                        /*isForceEnd = true;
                        if (unit.Data.IsAttackInRange() && unit.Data.IsInScreen())
                        {
                            targetPosition = unit.Data.position;
                            if (PveFindPathManager.Instance.CheckIsWalkable(unit.Data.position, unit.Data.id))
                            {
                                position = unit.Data.position;
                            }
                            else
                            {
                                targetPosition = unit.Data.lockTarget.Data.position;
                                needRepath = true;
                            }
                        }
                        else
                        {
                            targetPosition = unit.Data.lockTarget.Data.position;
                        }*/
                        UpdateEnemyMelee();
                        return;

                    }
                    else
                    {
                        targetPosition = unit.Data.attackPosition;
                        if (PveGlobalVlues.enemyUseAttackPoint)
                        {
                            if (unit.Data.IsAttackInRange() && Vector3.Distance(unit.Data.attackPosition, unit.Data.position) <= 0.1f)
                            {
                                if (!unit.Data.IsInScreen())
                                {
                                    unit.Data.attackPosition = Vector3.zero;
                                    return;
                                    //unit.Data.SetTargetPosition(unit.Data.lockTarget.Data.position);
                                }
                                
                                targetPosition = unit.Data.position;
                                position = unit.Data.attackPosition;
                                unit.Data.hasReachAttackPosition = true;
                                return;
                            }

                            if (unit.Data.hasReachAttackPosition)
                            {
                                if (unit.Data.IsAttackInRange())
                                {
                                    if (PveFindPathManager.Instance.CheckIsWalkable(unit.Data.position, unit.Data.id))
                                    {
                                        position = unit.Data.position;
                                    }
                                    else
                                    {
                                        UpdateAStarPath(unit.Data.position, targetPosition,true);
                                        lastRepathTime = TimeManager.logicTime;
                                        UpdateRoadPath();
                                        lastRepathTarget = targetPosition;
                                    }
                                    return;
                                }
                                else
                                {
                                    targetPosition = unit.Data.attackPosition;
                                    unit.Data.hasReachAttackPosition = false;
                                }
                            }
                            //unit.Data.configMoveSpeed = unit.Data.config.moveSpeed;
                            //isForceEnd = true;
                        }
                        else
                        {
                            //unit.Data.configMoveSpeed = unit.Data.config.moveSpeed / 2;
                        }
                        //isForceEnd = true;
                    }
                }

                bool canRepath = lastRepathTarget != targetPosition && (!IsInRepathSuccessCD() && !IsInRepathFailCD());
                if (canRepath || needRepath)
                {
                    /*if (unit.Data.modelId == 9999)
                    {
                        pathList.Clear();
                        pathList.Add(unit.Data.position);
                        pathList.Add(targetPosition);
                    }
                    else*/
                    {
                        UpdateAStarPath(unit.Data.position, targetPosition,isForceEnd);
                    }

                    
                    if (needShowPath)
                    {
                        ShowPath();
                        needShowPath = false;
                    }

                    if (pathList.Count > 0)
                    {
                        lastRepathTarget = pathList[pathList.Count - 1];
                        if (unit.Data.attackPosition != Vector3.zero)
                        {
                            //Debug.LogError("目标位置"+lastRepathTarget + " " + isFindPathSuccess + " " + unit.Data.attackPosition);
                            //unit.Data.attackPosition = lastRepathTarget;
                            //if (Vector3.Distance(unit.Data.attackPosition, lastRepathTarget) < 0.5f)
                            {
                                unit.Data.attackPosition = lastRepathTarget;
                            }
                            //else
                            {
                                //Debug.LogError("有差距" + unit.Data.attackPosition + " " + lastRepathTarget + " " + unit.Data.id);
                            }
                        }
                        
                        //PveFindPathManager.Instance.UpdateSingleCollider(unit.Data.id,pathList[pathList.Count - 1]);
                    }
                    else
                    {
                        //PveFindPathManager.Instance.UpdateSingleCollider(unit.Data.id,targetPosition);
                        lastRepathTarget = targetPosition;
                    }
                    
                    //unit.Data.attackPosition = lastRepathTarget;
                    lastRepathTime = TimeManager.logicTime;
                    RefreshRepathCD();
                    needRepath = false;
                }
                //lastRepathTarget = targetPosition;
            }
            UpdateRoadPath();
        }

        private void RefreshRepathCD()
        {
            repathCd = Random.Range(0.3f, 0.8f);
        }
        
        private void UpdateManualMoving()
        {
            if (unit.Data.isGoingToHidePoint)
            {
                if (lastTargetPosition != unit.Data.targetHidingPoint)
                {
                    lastTargetPosition = unit.Data.targetHidingPoint;
                    UpdateAStarPath(unit.Data.position,lastTargetPosition);
                }
                UpdateRoadPath();
                if (pathList.Count == 0)
                {
                    unit.Data.isGoingToHidePoint = false;
                }
            }
            else if (unit.Data.manualForward.sqrMagnitude <= 0.001f && unit.Data.moveSpeed == 0)
            {
                lastManualForward = Vector3.zero;
            }
            else
            {
                var forward = unit.Data.manualForward;
                if (unit.Data.manualForward.sqrMagnitude <= 0.001f)
                {
                    //forward = unit.Data.targetForward;
                    unit.Data.targetMoveSpeed = 0;
                }
                else
                {
                    unit.Data.targetMoveSpeed = unit.Data.configMoveSpeed;
                }

                bool doForward = unit.Data.manualAimForward.sqrMagnitude < 0.001f && !unit.Data.IsAttackInRange() &&
                               !unit.Data.isMoveAttacking && !unit.Data.isReloading;
                                                   
                var target = position + unit.Data.configMoveSpeed * TimeManager.LogicDeltaTime * forward.normalized;
                if (PveFindPathManager.Instance.CheckIsOutOfBound(target))
                {
                    unit.Data.manualForward = Vector3.zero;
                    return;
                }
                else if (PveFindPathManager.Instance.CheckIsCanWalkForward(target,forward,unit.Data.id) || PveManager.Instance.isInPve || PveManager.Instance.isToRpg)
                {
                    pathList.Clear();
                    //if (!unit.Data.isMoveAttacking && !unit.Data.IsAttackInRange())
                    if (doForward)
                    {
                        unit.Data.SetTargetForward(forward);
                    }
                    position = target;
                    //Debug.LogError(unit.Data.configMoveSpeed + " " + Time.deltaTime);
                    //Debug.LogError(Vector3.Distance(unit.Data.position,position));
                    lastManualForward = Vector3.zero;
                    lastManualAvailablePosition = Vector3.zero;
                }
                else
                {
                    unit.Data.manualForward = Vector3.zero;
                    //if (lastManualForward == Vector3.zero || Vector3.Angle(forward,lastManualForward) >= 10 || pathList.Count == 0)
                    {
                        Vector3 position = unit.Data.position;
                        if (lastManualForward == Vector3.zero)
                        {
                            lastManualForward = forward;
                        }
                        var isSuccess =
                            PveFindPathManager.Instance.GetFirstAvailablePosition(ref position, lastManualForward,
                                unit.Data.id);
                        bool needRepath = true;
                        if (lastManualAvailablePosition == Vector3.zero)
                        {
                            lastManualAvailablePosition = position;
                            availablePositionTime = TimeManager.logicTime;
                        }
                        else if (Vector3.Distance(lastManualAvailablePosition, position) <= 0.5f && TimeManager.logicTime - availablePositionTime <= 1)
                        {
                            needRepath = false;
                        }
                        else
                        {
                            availablePositionTime = 0;
                            lastManualAvailablePosition = Vector3.zero;
                        }
                        if (isSuccess)
                        {
                            if (needRepath)
                            {
                                UpdateAStarPath(unit.Data.position, position);
                                lastManualForward = forward;
                            }
                        }
                        else
                        {
                            lastManualForward = forward;
                            pathList.Clear();
                        }
                    }
                    UpdateRoadPath(doForward);
                    unit.Data.manualForward = unit.Data.targetForward;
                }
            }
        }
    }
}